import { _decorator, Component, Input, input, Node } from 'cc'
const { ccclass, property } = _decorator
import { TileMapManager } from 'db://assets/Ts/Tile/TileMapManager'
import { createUINode } from 'db://assets/utils/index'
import { PlayerManager } from 'db://assets/Ts/Player/PlayerManager'
import { WodenSkeletonManager } from 'db://assets/Ts/WoodenSkeleton/WodenSkeletonManager'
import Levels, { ILevel } from 'db://assets/Ts/Levels/index'
import DataManager from 'db://assets/Runtime/DataManager'
import EventManager from 'db://assets/Runtime/EventManager'
import { TILE_WIDTH, TILE_HEIGHT } from 'db://assets/Ts/Tile/TileManager'
import { ENTITY_STATE_ENUM, ENTITY_TYPE_ENUM, EVENT_ENUM } from 'db://assets/Ts/Enums/index'
import { DoorManager } from 'db://assets/Ts/Door/DoorManager'
import { IronSkeletonManager } from 'db://assets/Ts/IronSkeleton/IronSkeletonManager'
import { BurstManager } from '../Burst/BurstManager'
import { SpikesManager } from '../Spikes/SpikesManager'
// 这是一个装饰器，用于将 BattleManager 类标记为 Cocos Creator 中的一个组件类
@ccclass('BattleManager')
export class BattleManager extends Component {
  level: ILevel
  stage: Node

  protected onLoad(): void {
    DataManager.Instance.levelIndex = 1
    EventManager.Instance.on(EVENT_ENUM.NEXT_LEVEL, this.nextLevel, this)
    EventManager.Instance.on(EVENT_ENUM.PLAYER_MOVE_END, this.checkArrived, this)
  }

  protected onDestroy(): void {
    EventManager.Instance.off(EVENT_ENUM.NEXT_LEVEL, this.nextLevel)
  }

  start() {
    // 这是 Cocos Creator 中的生命周期方法之一。
    // 当组件被启用时，这个方法会被自动调用。
    this.generateStage()
    // 在这里，start() 方法调用了 generateTileMap() 方法，以初始化瓦片地图。
    this.initLevel()
  }
  async initLevel() {
    const level = Levels[`level${DataManager.Instance.levelIndex}`]
    if (level) {
      this.clearLevel()
      this.level = level

      DataManager.Instance.mapInfo = this.level.mapInfo
      DataManager.Instance.mapRowCount = this.level.mapInfo.length || 0
      DataManager.Instance.mapColumnCount = this.level.mapInfo[0].length || 0
      // 调用 generateTileMap() 方法，生成和初始化瓦片地图。
      await this.generateTileMap()
      // 调用 generateBursts() 方法，生成地裂效果。
      await this.generateBursts()
      await this.generateSpikes()
      // 调用 generateDoor() 方法，生成门。
      await this.generateDoor()
      // 调用 generatePlayer() 方法，生成玩家角色。
      await this.generatePlayer()
      // 调用 generateWodenSkeletons() 方法，生成战斗精灵。
      await this.generateEnemies()
    }
  }

  nextLevel() {
    DataManager.Instance.levelIndex++
    this.initLevel()
  }

  clearLevel() {
    this.stage.destroyAllChildren()
    DataManager.Instance.reset()
  }

  generateStage() {
    // 这是生成舞台的方法。
    this.stage = createUINode()
    this.stage.setParent(this.node)
  }

  // 此方法负责实际生成和初始化瓦片地图
  async generateTileMap() {
    // 调用 createUINode() 创建另一个用户界面节点，
    // 表示瓦片地图，这个节点被赋值为 tileMap 变量。
    const tileMap = createUINode()
    // 将 tileMap 节点设置为 stage 节点的子节点。
    tileMap.setParent(this.stage)
    // 为 tileMap 节点添加一个 TileMapManager 组件实例，
    // TileMapManager 是用于管理瓦片地图的功能和数据结构。
    const tileMapManager = tileMap.addComponent(TileMapManager)
    // 调用 tileMapManager 的 init() 方法，进行瓦片地图的初始化操作。
    await tileMapManager.init()

    this.adaptPos()
  }

  async generateBursts() {
    const promise = []
    for (let i = 0; i < this.level.bursts.length; i++) {
      const burst = this.level.bursts[i]
      const burstNode = createUINode()
      burstNode.setParent(this.stage)
      const burstManager = burstNode.addComponent(BurstManager)
      promise.push(burstManager.init(burst))
      DataManager.Instance.bursts.push(burstManager)
    }
    await Promise.all(promise)
  }

  async generateSpikes() {
    const promise = []
    for (let i = 0; i < this.level.spikes.length; i++) {
      const spike = this.level.spikes[i]
      const spikesNode = createUINode()
      spikesNode.setParent(this.stage)
      const spikesManager = spikesNode.addComponent(SpikesManager)
      promise.push(spikesManager.init(spike))
      DataManager.Instance.spikes.push(spikesManager)
    }
    await Promise.all(promise)
  }

  async generateDoor() {
    const door = createUINode()
    door.setParent(this.stage)
    const doorManager = door.addComponent(DoorManager)
    await doorManager.init(this.level.door)
    DataManager.Instance.door = doorManager
  }

  async generatePlayer() {
    const player = createUINode()
    player.setParent(this.stage)
    const playerManager = player.addComponent(PlayerManager)
    await playerManager.init(this.level.player)
    DataManager.Instance.player = playerManager
    EventManager.Instance.emit(EVENT_ENUM.PLAYER_BORN, true)
  }

  async generateEnemies() {
    const promise = []
    for (let i = 0; i < this.level.enemies.length; i++) {
      const enemy = this.level.enemies[i]
      const enemiesNode = createUINode()
      enemiesNode.setParent(this.stage)
      const Manager = enemy.type === ENTITY_TYPE_ENUM.SKELETON_WOODEN ? WodenSkeletonManager : IronSkeletonManager
      const manager = enemiesNode.addComponent(Manager)
      promise.push(manager.init(enemy))
      DataManager.Instance.enemies.push(manager)
    }
    await Promise.all(promise)
  }
  //
  adaptPos() {
    const { mapRowCount, mapColumnCount } = DataManager.Instance
    const disX = (mapRowCount * TILE_WIDTH) / 2
    const disY = (mapColumnCount * TILE_HEIGHT) / 2

    this.stage.setPosition(-disX, disY)
  }
  checkArrived() {
    const { x: playerX, y: playerY } = DataManager.Instance.player
    const { x: doorX, y: doorY, state: doorState } = DataManager.Instance.door
    if (playerX === doorX && playerY === doorY && doorState === ENTITY_STATE_ENUM.DEATH) {
      console.log('player arrived')
      EventManager.Instance.emit(EVENT_ENUM.NEXT_LEVEL)
    }
  }
}
